// filename: AsyncTcpSocket.cpp
// author: enic
// date: 2015-06-26

#include "AsyncTcpSocket.h"
#include "AsyncTcpAcceptor.h"

AsyncTcpAcceptor::AsyncTcpAcceptor(SocketEngine* pSocketEngine) :
	m_acceptor(pSocketEngine->GetIoServiceReference())
{
	m_pSocketEngine = pSocketEngine;
	m_pTcpSocketCurAccept = NULL;
	m_FuncCloseSink = nullptr;
	m_FuncAcceptSink = nullptr;
}

AsyncTcpAcceptor::~AsyncTcpAcceptor()
{
	if (m_pTcpSocketCurAccept)
	{
		m_pSocketEngine->ReleaseAsyncTcpSocket(m_pTcpSocketCurAccept);
		m_pTcpSocketCurAccept = NULL;
	}
}

void AsyncTcpAcceptor::Close()
{
	if (m_acceptor.is_open())
	{
		m_acceptor.close();

		if (m_FuncCloseSink)
		{
			m_FuncCloseSink(this);
		}
	}

	if (m_pTcpSocketCurAccept)
	{
		m_pSocketEngine->ReleaseAsyncTcpSocket(m_pTcpSocketCurAccept);
		m_pTcpSocketCurAccept = NULL;
	}
}

void AsyncTcpAcceptor::SetCloseSink(TAcceptorCloseSink closeSink)
{
	m_FuncCloseSink = closeSink;
}

void AsyncTcpAcceptor::Bind(const IpEndpoint& ipEndpint)
{
	boost::asio::ip::tcp::endpoint endpoint(
		boost::asio::ip::address::from_string(ipEndpint.GetIpAsString()), ipEndpint.GetPort());
	
	m_acceptor.open(endpoint.protocol());
	m_acceptor.bind(endpoint);
}

void AsyncTcpAcceptor::Listen(uint32_t nMax)
{
	m_acceptor.listen(nMax);
}

void AsyncTcpAcceptor::SetAcceptSink(TAcceptSink acceptSink)
{
	m_FuncAcceptSink = acceptSink;
}

void AsyncTcpAcceptor::AsyncAccept()
{
	AsyncTcpSocket* pSocket = dynamic_cast<AsyncTcpSocket*>(m_pSocketEngine->CreateAsyncTcpSocket());
	XASSERT(NULL != pSocket);

	m_pTcpSocketCurAccept = pSocket;

	m_acceptor.async_accept(pSocket->GetTcpSocket(), 
		[this](const boost::system::error_code& ec)
		{
			//OnAsyncAccept();
			XLOG(XINFO) << __FUNCTION__ << std::endl;

			if (!ec)
			{
				if (m_FuncAcceptSink)
				{
					m_FuncAcceptSink(this, m_pTcpSocketCurAccept);
				}

				m_pTcpSocketCurAccept->AsyncRead();
				m_pTcpSocketCurAccept = NULL;
				AsyncAccept();
			}
			else
			{
				std::cout << ec.message() << std::endl;
			}

		});
}



void AsyncTcpAcceptor::OnAsyncAccept(IAsyncTcpSocket* pSocket)
{

}

